﻿using BMSPlatform.DeviceCommunication;
using DataManage;
using ServiceLayerManagement;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BMSPlatform.ViewModel
{
    public class ApplicationUpgradeViewModel : BaseViewModel
    {
        #region 非通知类变量、委托
        public byte[] BinData { get; set; }
        public int ProgressBarMaxValue { get; set; }
        /// <summary>
        /// 消息队列
        /// </summary>
        public ConcurrentQueue<string> MessageQueue { get; set; }
        /// <summary>
        /// 进度条
        /// </summary>
        public ConcurrentQueue<double> ProgressBarValueQueue { get; set; }

        public Action<bool> UpgradeEnableAction;
        #endregion

        #region 通知类变量
        private ObservableCollection<string> processInfos;
        public ObservableCollection<string> ProcessInfos { get => processInfos; set { processInfos = value; NotifyPropertyChanged(); } }

        private string binFilePath;
        public string BinFilePath { get => binFilePath; set { binFilePath = value; NotifyPropertyChanged(); } }

        private byte selectedDeviceAdress;
        public byte SelectedDeviceAdress { get => selectedDeviceAdress; set { selectedDeviceAdress = value; NotifyPropertyChanged(); } }

        private double progressBarCurrentValue = 0;
        /// <summary>
        /// 进度条当前值
        /// </summary>
        public double ProgressBarCurrentValue { get => progressBarCurrentValue; set { progressBarCurrentValue = value; NotifyPropertyChanged(); } }

        private bool upgradeEnable = true;
        /// <summary>
        /// 升级时的控件使能
        /// </summary>
        public bool UpgradeEnable { get => upgradeEnable; set { upgradeEnable = value; NotifyPropertyChanged(); } }

        private List<string> binFileInfo;
        /// <summary>
        /// Bin文件数据信息
        /// </summary>
        public List<string> BinFileInfo { get => binFileInfo; set { binFileInfo = value; NotifyPropertyChanged(); } }
        #endregion

        public void OnSystemUpgrade()
        {
            if (!Check()) return;

            if (MessageQueue == null) MessageQueue = new ConcurrentQueue<string>();
            if (ProgressBarValueQueue == null) ProgressBarValueQueue = new ConcurrentQueue<double>();

            if (ProcessInfos == null)
            {
                ProcessInfos = new ObservableCollection<string>();
            }
            else
            {
                ClearHisdata();
            };

            //设置进度条
            ProgressBarMaxValue = (BinData.Length / 200) + (BinData.Length % 200 == 0 ? 0 : 1);
            Task.Factory.StartNew
            (() =>
            {
                UpgradeEnableAction?.Invoke(false);
                BinFileUpgradeCommandDownLoad binFileUpgradeCommandDownLoad = new BinFileUpgradeCommandDownLoad();
                binFileUpgradeCommandDownLoad.MessageTrans += AddMessageQueue;
                binFileUpgradeCommandDownLoad.ProcessBarEvent += AddCurrentValueQueue;
                binFileUpgradeCommandDownLoad.CommanLoad(BinData, SelectedDeviceAdress);
                while (true)
                {
                    if (MessageQueue.Count <= 0 && ProgressBarValueQueue.Count <= 0)
                    {
                        UpgradeEnableAction?.Invoke(true);
                        break;
                    }
                    AppHelper.Delay(100);
                }
              
            }
            );
        }

        public byte[] ReadBinFile()
        {
            int file_len;//bin文件长度
            byte[] binchar = new byte[0];
            using (FileStream Myfile = new FileStream(binFilePath, FileMode.Open, FileAccess.Read))
            {
                BinaryReader binreader = new BinaryReader(Myfile);
                file_len = (int)Myfile.Length;//获取bin文件长度
                StringBuilder str = new StringBuilder();
                binchar = binreader.ReadBytes(file_len);
                binreader.Close();
            }
            return binchar;
        }

        public void AddMessageQueue(string strMessage)
        {
            MessageQueue.Enqueue(strMessage);
        }

        public void AddCurrentValueQueue(double currentValue)
        {
            ProgressBarValueQueue.Enqueue(currentValue);
        }

        public void ClearHisdata()
        {
            while (MessageQueue.TryDequeue(out _));

            while (ProgressBarValueQueue.TryDequeue(out _)) ;

            ProgressBarCurrentValue = 0;
            ProcessInfos.Clear();
        }

        private bool Check()
        {
            if (string.IsNullOrWhiteSpace(BinFilePath))
            {
                MessageHelper.Info("BIN文件路径不可为空");
                return false;
            }

            if (!Collection.DeviceAdress.ContainsKey(SelectedDeviceAdress))
            {
                MessageHelper.Info("请选择设备类型");
                return false;
            }

            if (BinData == null || BinData?.Length <= 0)
            {
                MessageHelper.Info("BIN文件数据读取失败");
                return false;
            }

            if (!GlobalData.CANConnectState)
            {
                MessageHelper.Info("CAN通讯处于断开状态");
                return false;
            }
            string md5 = Path.GetFileNameWithoutExtension(BinFilePath);
            //MD5检查(目的：检查文件完整性)
            if (md5.IndexOf("md5=", StringComparison.OrdinalIgnoreCase) < 0)
            {
                MessageHelper.Info("文件名未含有MD5");
                return false;
            }

            byte[] md5Bytes = CrcCheckUtily.GetMD5(BinFilePath);
            if(md5Bytes == null || md5Bytes.Length <= 0)
            {
                MessageHelper.Info("MD5计算错误，结果值为空");
                return false;
            }

            string resultMd5 = "";
            for(int i = 0; i < md5Bytes.Length; i++)
            {
                resultMd5 += md5Bytes[i].ToString("X2");
            }
            if(md5.IndexOf(resultMd5, StringComparison.OrdinalIgnoreCase) < 0)
            {
                MessageHelper.Info("MD5不匹配");
                return false;
            }

            return true;
        }
        /// <summary>
        /// Bin文件解析
        /// </summary>
        /// <returns></returns>
        public void BinFileParse()
        {
            List<string> list = new List<string>();
            string text;
            if (BinData == null || BinData?.Length <= 22) return;

            text = "芯片型号：";
            if (Collection.STMType.ContainsKey(BinData[6])) text += BinData[6];
            list.Add(text);
            list.Add($"硬件版本：{BinData[7]}.{BinData[8]}");
            list.Add($"软件版本：{BinData[9]}.{BinData[10]}");
            list.Add($"BOOT版本：{BinData[11]}.{BinData[12]}");
            list.Add($"编译时间：{BinData[13]}{BinData[14]}{BinData[15]}{BinData[16]}年{BinData[17]}{BinData[18]}月{BinData[19]}{BinData[20]}日");
            BinFileInfo = list;
        }
    }
}
